<script setup lang="ts">
import {ref, h} from 'vue'
import {
  NInput,
  NSwitch,
  NFormItem,
  DropdownOption,
  TreeOption,
  TransferRenderSourceList
} from 'naive-ui'
import {useTable} from '@/composables/useTable'
import {fetchRoleDetails, fetchRolePage, fetchRoleSave, fetchRoleUpdate} from "@/api/role"
import {
  ClickType,
  DEFAULT_MENU_MODEL,
  useColumns,
  useContextMenuOptions,
  useFormRules,
  useMenuDownOptions,
} from '@/views/manager/role/mock/useRoleConfig'
import {createBooleanComputed} from "@/utils/to"
import BaseCrudPage from '@/components/page/BaseCrudPage.vue'
import BaseFormModal from '@/components/modal/BaseFormModal.vue'
import GgIcon from "@/components/icon/gg-icon.vue"
import SearchForm from "@/views/manager/role/components/SearchForm.vue";
import {Option} from "naive-ui/es/transfer/src/interface";
import {NTree} from "naive-ui/es/tree";
import {fetchMenuTree} from "@/api/menu";

defineOptions({name: 'Role'})

// 状态管理
const optionType = ref<ClickType>(ClickType.NONE)
const showModal = ref(false)
const formValue = ref<Role.BaseInfo>()
const loading = ref(false)

// 表格配置
const {
  dataRef,
  loading: tableLoading,
  pagination,
  tableConfig,
  handlePageChange,
  refresh,
  rowKey,
  reset
} = useTable<Role.BaseInfo[]>({
  pageSize: 10,
  api: (params) => fetchRolePage({...params}),
  immediate: true,
  minHeight: 560,
  maxHeight: 560
})


// 处理点击事件
async function handlerClick(type: ClickType, row: Role.BaseInfo) {
  optionType.value = type
  if (type == ClickType.UPDATE) {
    formValue.value = {...row}
    showModal.value = true
    showHomeMenu.value = {
      id: row.home.id,
      title: row.home?.title,
      iconShow: row.home?.icon
    }
    await setMenuOptions()
    await setMenuValues(row.roleId)
  } else if (type == ClickType.ADD) {
    formValue.value = {...DEFAULT_MENU_MODEL}
    showModal.value = true
  } else if (type === ClickType.DELETE && row.roleId) {
  }
  refresh()
}

// 处理新增按钮点击
function handleAdd() {
  optionType.value = ClickType.ADD
  formValue.value = {...DEFAULT_MENU_MODEL}
  showModal.value = true
}

const columns = useColumns(handlerClick)
const contextMenuOptions = useContextMenuOptions(handlerClick)
const rules = useFormRules()
const menuDownOptions = useMenuDownOptions()

// 计算属性
const statusBoolean = createBooleanComputed(formValue, 'status')

// 处理表单提交
async function handleSubmit(model: Role.BaseInfo) {
  try {
    loading.value = true
    if (optionType.value === ClickType.UPDATE) {
      await fetchRoleUpdate(
        {
          ...model,
          home: showHomeMenu.value.id,
          roleId: model.roleId,
          menuIds: menuValues.value
        }
      )
    } else if (optionType.value === ClickType.ADD) {
      await fetchRoleSave(
        {
          ...model,
          home: showHomeMenu.value.id,
          roleId: null,
          menuIds: menuValues.value
        }
      )
    } else if (optionType.value === ClickType.DELETE) {
      window.$message?.warning("暂时不支持删除功能")
    }
    console.log('menuValues', menuValues.value)
    showModal.value = false
    refresh()
  } catch (error) {
    window.$message?.error('操作失败：' + error)
  } finally {
    loading.value = false
  }
}

const showHomeMenu = ref({
  title: "",
  id: 0,
  icon: ""
})

function handleSelect(key: string | number, option: DropdownOption) {
  showHomeMenu.value = {
    id: key as number,
    title: option.label as string,
    iconShow: option.iconShow as string
  }
}

const menuValues = ref<[]>();
const menuTree = ref<Option[]>([]);
const menuOptions = ref<Option[]>([]);

async function setMenuValues(roleId: number | string) {
  const roleDetails = await fetchRoleDetails(roleId);
  menuValues.value = roleDetails.menuIds
}

//设定当前菜单列表
async function setMenuOptions() {
  const menuTreeParam = await fetchMenuTree();
  menuTree.value = transfer(menuTreeParam);
  // menuOptions.value = transfer(menuTreeParam);
  menuOptions.value = flattenTree(menuTreeParam)
}

function transfer(transfer: Menu.MenuModel[]): Option[] {
  const transformMenuItem = (menu: Menu.MenuModel): Option | null => {

    const option: Option = {
      label: menu.title,
      value: menu.id,
      children: []
    }
    // 递归处理子菜单（仅处理有效子项）
    if (menu.children && menu.children?.length > 0) {
      const children = menu.children.map(transformMenuItem).filter(Boolean) as Option[];
      if (children.length > 0) {
        option.children = children;
      }
    }
    // 清理空children属性
    if (option.children?.length === 0) {
      delete option.children
    }
    return option;
  }
  return transfer.map(transformMenuItem).filter(Boolean) as Option[];
}

function flattenTree(transfer?: Menu.MenuModel[]): Option[] {
  if (!Array.isArray(transfer)) return []; // 保护措施，防止 undefined 传入

  const flattenNode = (menu: Menu.MenuModel): Option[] => {
    const option: Option = {
      label: menu.title,
      value: menu.id
    };

    if (Array.isArray(menu.children) && menu.children.length > 0) {
      return [option, ...menu.children.flatMap(flattenNode)];
    }

    return [option];
  };

  return transfer.flatMap(flattenNode);
}

const renderSourceList: TransferRenderSourceList = function ({
                                                               onCheck,
                                                               pattern
                                                             }) {
  return h(NTree, {
    style: 'margin: 0 4px;',
    keyField: 'value',
    checkable: true,
    selectable: false,
    blockLine: true,
    checkOnClick: true,
    data: menuTree.value as unknown as TreeOption[],
    pattern,
    checkedKeys: menuValues.value,
    onUpdateCheckedKeys: (checkedKeys: Array<string | number>) => {
      onCheck(checkedKeys)
    }
  })
}
</script>

<template>
  <BaseCrudPage
    title="角色管理"
    :loading="tableLoading"
    :data="dataRef"
    :columns="columns"
    :pagination="pagination"
    :table-config="tableConfig"
    :context-menu-options="contextMenuOptions"
    :row-key="rowKey"
    @update:page="handlePageChange"
    @add="handleAdd"
  >
    <template #search>
      <SearchForm
        :on-search="refresh"
        :on-reset="reset"
      />
    </template>

    <template #modal>
      <BaseFormModal
        v-model:show="showModal"
        :title="optionType === ClickType.UPDATE ? '修改角色' : '新增角色'"
        :model="formValue"
        :rules="rules"
        width="800px"
        :loading="loading"
        @submit="handleSubmit"
      >
        <n-form-item label="角色名称" path="roleName">
          <n-input v-model:value="formValue.roleName" placeholder="请输入角色名称"/>
        </n-form-item>

        <n-form-item label="角色CODE" path="roleCode">
          <n-input v-model:value="formValue.roleCode" placeholder="请输入角色CODE"/>
        </n-form-item>

        <n-form-item label="角色说明" path="description">
          <n-input v-model:value="formValue.description" placeholder="请输入角色说明"/>
        </n-form-item>

        <n-form-item label="角色状态" path="statusBoolean">
          <n-switch v-model:value="statusBoolean"/>
        </n-form-item>

        <n-form-item label="首页" path="menuHome">
          <n-dropdown
            trigger="hover"
            :options="menuDownOptions"
            @select="handleSelect"
          >
            <n-button>
              <template #icon>
                <GgIcon :name="showHomeMenu.iconShow"/>
              </template>
              {{ showHomeMenu.title || '请选择首页' }}
            </n-button>
          </n-dropdown>
        </n-form-item>
        <n-form-item label="用户角色:" path="menuIds">
          <n-transfer
            size="small"
            v-model:value="menuValues"
            :options="menuOptions"
            :render-source-list="renderSourceList"
            source-filterable
            virtual-scroll
            source-title="可选菜单"
            target-title="已选菜单"
          />
        </n-form-item>
      </BaseFormModal>
    </template>
  </BaseCrudPage>
</template>
<style scoped>
.container {
  padding: 16px;
  background-color: #f5f7fa;
  min-height: 100%;
}

:deep(.n-data-table) {
  background-color: #fff;
  border-radius: 4px;
}

:deep(.n-card) {
  background-color: transparent;
  box-shadow: none;
}

:deep(.n-card-header) {
  padding: 0 0 16px 0;
}

:deep(.n-button:not(:last-child)) {
  margin-right: 12px;
}

:deep(.n-form-item-label) {
  font-weight: 500;
}
</style>
